package br.com.websec.cnab;

import java.util.Date;

import br.com.websec.banco.Banco;
import br.com.websec.util.CnabUtil;
import br.com.websec.util.FuncoesUtil;
import br.com.websec.util.UtilException;


public class Cabecalho extends CnabUtil{
	
	private String codigoBanco;
	
	private String loteServico;

	private int registroCabecalho;

	private int tipoInscricaoEmpresa;

	private String razaoSocialEmpresa;

	private String cpfCnpjEmpresa;

	private String codConvBanco;

	private String agencia;

	private String digitoAgencia;

	private String posto;

	private String conta;

	private String digitoConta;

	private String digitoAgenciaConta;

	private String nomeBanco;

	private int tipoOperacao;

	private Date dataGeracao;

	private int horaGeracaoArquivo;

	private Integer sequenciaArquivo;

	private String versaoLayout;

	private String densidadeArquivo;

	private String usoBanco;

	private String usoEmpresa;

	// Cobrança sem papel
	private String usoVans;

	private String tipoServico;

	private String ocorrencias;
	

	public Cabecalho() {

		setLoteServico("0000");
		setRegistroCabecalho(0);
		setTipoOperacao(1);
		setVersaoLayout("030");
	}

	public Cabecalho(String line) throws UtilException {

		this();
		parseLine(line);
	}
	
	public String getAgencia() {

		return agencia;
	}

	public void setAgencia(final String agencia) {

		this.agencia = agencia;
	}

	public String getCodigoBanco() {

		return codigoBanco;
	}

	public void setCodigoBanco(final String codigoBanco) {

		this.codigoBanco = codigoBanco;
	}

	public String getCodigoConvenvioBanco() {

		return codConvBanco;
	}

	public void setCodigoConvenioBanco(final String codConvenio) {

		this.codConvBanco = codConvenio;
	}

	public String getConta() {

		return conta;
	}

	public void setConta(final String conta) {

		this.conta = conta;
	}

	public String getCpfCnpjEmpresa() {

		return cpfCnpjEmpresa;
	}

	public void setCpfCnpjEmpresa(final String cpfCnpjEmpresa) {

		this.cpfCnpjEmpresa = cpfCnpjEmpresa;
	}

	public Date getDataGeracao() {

		return dataGeracao;
	}

	public void setDataGeracao(final Date dataGeracao) {

		this.dataGeracao = dataGeracao;
	}

	public String getDensidadeArquivo() {

		return densidadeArquivo;
	}

	public void setDensidadeArq(final String densidadeArquivo) {

		this.densidadeArquivo = densidadeArquivo;
	}

	public String getDigitoAgenciaConta() {

		return digitoAgenciaConta;
	}

	public void setDigitoAgenciaConta(final String digAgenciaConta) {

		this.digitoAgenciaConta = digAgenciaConta;
	}

	public String getDigitoAgencia() {

		return digitoAgencia;
	}

	public void setDigitoAgencia(final String digitoAgencia) {

		this.digitoAgencia = digitoAgencia;
	}

	public String getPosto() {

		return posto;
	}

	public void setPosto(String posto) {

		this.posto = posto;
	}

	public String getDigitoConta() {

		return digitoConta;
	}

	public void setDigitoConta(final String digitoConta) {

		this.digitoConta = digitoConta;
	}

	public int getHoraGeracaoArquivo() {

		return horaGeracaoArquivo;
	}

	public void setHoraGeracaoArquivo(final int horaGeracao) {

		this.horaGeracaoArquivo = horaGeracao;
	}

	public String getLoteServico() {

		return loteServico;
	}

	private void setLoteServico(final String loteServico) {

		this.loteServico = loteServico;
	}

	public String getNomeBanco() {

		return nomeBanco;
	}

	public void setNomeBanco(final String nomeBanco) {

		this.nomeBanco = nomeBanco;
	}

	public String getOcorrencias() {

		return ocorrencias;
	}

	public void setOcorrencias(final String ocorrencias) {

		this.ocorrencias = ocorrencias;
	}

	public String getRazaoSocialEmpresa() {

		return razaoSocialEmpresa;
	}

	public void setRazaoEmpresa(final String razaoEmpresa) {

		this.razaoSocialEmpresa = razaoEmpresa;
	}

	public int getRegistroCabecalho() {

		return registroCabecalho;
	}

	private void setRegistroCabecalho(final int registroCabecalho) {

		this.registroCabecalho = registroCabecalho;
	}

	public Integer getSequenciaArquivo() {

		return sequenciaArquivo;
	}

	public void setSequenciaArquivo(final Integer sequenciaArquivo) {

		this.sequenciaArquivo = sequenciaArquivo;
	}

	/**
	 * Indica o tipo de inscricao da empresa.<br>
	 * 1 - CPF<br>
	 * 2 - CNPJ<br>
	 */
	public int getTipoInscricaoEmpresa() {

		return tipoInscricaoEmpresa;
	}

	public void setTipoInscricaoEmpresa(final int tipoInscricaoEmpresa) {

		this.tipoInscricaoEmpresa = tipoInscricaoEmpresa;
	}

	public String getTipoServico() {

		return tipoServico;
	}

	public void setTipoServico(final String tipoServico) {

		this.tipoServico = tipoServico;
	}

	public String getUsoBanco() {

		return usoBanco;
	}

	public void setUsoBanco(final String usoBanco) {

		this.usoBanco = usoBanco;
	}

	public String getUsoEmpresa() {

		return usoEmpresa;
	}

	public void setUsoEmpresa(final String usoEmpresa) {

		this.usoEmpresa = usoEmpresa;
	}

	public String getUsoVans() {

		return usoVans;
	}

	public void setUsoVans(final String usoVans) {

		this.usoVans = usoVans;
	}

	/*
	 * 1 - Remessa
	 * 2 - Retorno
	 */
	public int getTipoOperacao() {

		return tipoOperacao;
	}

	private void setTipoOperacao(final int tipoOperacao) {

		this.tipoOperacao = tipoOperacao;
	}

	public String getVersaoLayout() {

		return versaoLayout;
	}

	private void setVersaoLayout(final String versaoLayout) {

		this.versaoLayout = versaoLayout;
	}


	public String getLine() throws UtilException {
		StringBuilder line = new StringBuilder();

		try {
			line.append(getRegistroCabecalho()); // Posição 001 a 001 - Identificação do Registro
			line.append("1"); // Posição 002 a 002 - Identificação do Arquvo de remessa
			if (getCodigoBanco().equals(Banco.BANCO_DO_BRASIL)){
				line.append(formatar(COBRANCA, EnumTipo.X, 7, 0)); // Posição 003 a 009 - Literacao de remessa
			}
			else {
				line.append(formatar(REMESSA, EnumTipo.X, 7, 0)); // Posição 003 a 009 - Literacaoo de remessa
			}
			line.append("01"); // Posição 010 a 011 - Código do servico (01)
			
			
			line.append(formatar(COBRANCA, EnumTipo.X, 15, 0));// Posição 012 a 026 - Literal Servico
			

			// Informacao personalizada para o banco do brasil
			if (getCodigoBanco().equals(Banco.BANCO_DO_BRASIL)) {
				line.append(FuncoesUtil.strZero(getAgencia(), 4));// Posição 027 a 030 - Prefixo da agencia: Número da Agência onde está cadastrado o convênio líder do cedente 
				line.append(getDigitoAgencia());// Posição 031 a 031 - Digito verificador da agencia
				line.append(FuncoesUtil.strZero(getConta(), 8));// Posição 032 a 039 - Numero da conta
				line.append(getDigitoConta());// Posição 040 a 040 - Digito verificador da conta
				line.append(FuncoesUtil.strZero("", 6));// Posição 041 a 046 - Complemento do Registro: “000000”
				
			} else if (getCodigoBanco().equals(Banco.ITAU)) {
				line.append(FuncoesUtil.strZero(getAgencia(), 4));// Posição 027 a 030 - Agência Mantedora da conta
				line.append("00");	// 031 a 032 - Complemento de Registro
				line.append(formatar(getConta(), EnumTipo.$9, 5, 0));// 033 a 037 - Numero da conta corrente da empresa
				line.append(getDigitoConta());// 038 a 038 - Digito da conta
				line.append(FuncoesUtil.adicionaEspacos("", 8));// 039 a 046 - Complemento do Registro
			}
			else {
				line.append(FuncoesUtil.strZero(getCodigoConvenvioBanco(), 20));// Posição 027 a 046 Código da Empresa
			}
			line.append(formatar(getRazaoSocialEmpresa().toUpperCase(), EnumTipo.X, 30,0)); // Posição 047 a 076 - Nome da Empresa (Cedente)
			line.append(formatar(getCodigoBanco(), EnumTipo.$9, 3, 0));// Posição 077 a 079 - número do banco na camara de compensaco
			line.append(formatar(getNomeBanco().toUpperCase(), EnumTipo.X,15, 0));// Posição 080 a 094 - Nome do banco por extenso
			line.append(FuncoesUtil.dateToString(getDataGeracao(), DATA_DDMMAA_06));// Posição 095 a 100 -Data da gravacao do arquivo

			if (getCodigoBanco().equals(Banco.BANCO_DO_BRASIL)) {
				line.append(FuncoesUtil.strZero(getSequenciaArquivo()+ "", 7));// Posição 101 a 107 - Sequencial da remessa

				if (getCodigoConvenvioBanco().length() < 7) {
					line.append(FuncoesUtil.replicate(" ", 287)); // Posição 108 a 394 - Espaços em branco
				} else {
					line.append(FuncoesUtil.replicate(" ", 22)); // Posição 108 a 130 - Espaços em branco
					line.append(formatar(getCodigoConvenvioBanco(), EnumTipo.X, 7, 0)); // Posição 130 a 136 - Codigo do convenio lider 
					line.append(FuncoesUtil.replicate(" ", 258)); // Posição 136 a 394 - Espaço em branco
				}
			} else if (getCodigoBanco().equals(Banco.ITAU)) {
				line.append(FuncoesUtil.adicionaEspacos("", 294));// 101 - 394 - Espaços em branco
			} else {
				line.append(FuncoesUtil.replicate(" ", 8));// Posição 101 a 108 - Espaço em branco
				line.append(LITERAL_SISTEMA);// Posição 109 a 110 - Literal do Sistema (MX - Micro a micro)
				line.append(formatar(getSequenciaArquivo(), EnumTipo.$9, 7, 0)); // Posição 111 a 117 - Numero sequencial da remessa
				line.append(FuncoesUtil.replicate(" ", 277)); // Posição 118 a 394 - Espaço em branco
			}
			line.append(formatar(1, EnumTipo.$9, 6, 0)); // Sequencial do registro
			line.append((char) 13);
			line.append((char) 10);


		} catch (Exception e) {
			throw new UtilException(
					"Registro CNAB Cabecalho.\nErro ao escrever registro.\n"
							+ e.getMessage());
		}

		return FuncoesUtil.limpaAcentos(line.toString());
	}


	public void parseLine(final String line) throws UtilException {

		try {

			if (line == null) {
				throw new UtilException("Registro CNAB Cabecalho.\nLinha nula.");
			} else {
				// Identificador de retorno
				if ("2".equals(line.substring(1, 2))) {
					setCodigoBanco(line.substring(76, 79));
						setRegistroCabecalho(new Integer(line.substring(0, 1))
								.intValue());
						setTipoOperacao(2);
						setCodigoConvenioBanco(line.substring(26, 46));
						setRazaoEmpresa(line.substring(46, 76));
						setNomeBanco(line.substring(79, 94));
						setDataGeracao(FuncoesUtil.stringToDateDDMMAA(line
								.substring(94, 100).trim()));
						setSequenciaArquivo(Integer.parseInt(line.substring(
								394, 400)));
				} else {
					FuncoesUtil.mensagemInforma(
							"Arquivo não representa um arquivo de retorno padrão CNAB 400!");
				}
			}
		} catch (Exception e) {
			throw new UtilException(
					"Registro CNAB Cabecalho.\nErro ao ler registro.\n"
							+ e.getMessage());
		}
	}

	public Cabecalho(String codigoBanco, String loteServico,
			int registroCabecalho, int tipoInscricaoEmpresa,
			String razaoSocialEmpresa, String cpfCnpjEmpresa,
			String codConvBanco, String agencia, String digitoAgencia,
			String posto, String conta, String digitoConta,
			String digitoAgenciaConta, String nomeBanco, int tipoOperacao,
			Date dataGeracao, int horaGeracaoArquivo, Integer sequenciaArquivo,
			String versaoLayout, String densidadeArquivo, String usoBanco,
			String usoEmpresa, String usoVans, String tipoServico,
			String ocorrencias) {
		super();
		this.codigoBanco = codigoBanco;
		this.loteServico = loteServico;
		this.registroCabecalho = registroCabecalho;
		this.tipoInscricaoEmpresa = tipoInscricaoEmpresa;
		this.razaoSocialEmpresa = razaoSocialEmpresa;
		this.cpfCnpjEmpresa = cpfCnpjEmpresa;
		this.codConvBanco = codConvBanco;
		this.agencia = agencia;
		this.digitoAgencia = digitoAgencia;
		this.posto = posto;
		this.conta = conta;
		this.digitoConta = digitoConta;
		this.digitoAgenciaConta = digitoAgenciaConta;
		this.nomeBanco = nomeBanco;
		this.tipoOperacao = tipoOperacao;
		this.dataGeracao = dataGeracao;
		this.horaGeracaoArquivo = horaGeracaoArquivo;
		this.sequenciaArquivo = sequenciaArquivo;
		this.versaoLayout = versaoLayout;
		this.densidadeArquivo = densidadeArquivo;
		this.usoBanco = usoBanco;
		this.usoEmpresa = usoEmpresa;
		this.usoVans = usoVans;
		this.tipoServico = tipoServico;
		this.ocorrencias = ocorrencias;
	}
	
	

}
